package com.igoal.admin.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.mail.internet.MimeMessage;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

import com.igoal.dao.InfoQueueDAO;
import com.igoal.dao.MemberMailDAO;
import com.igoal.dto.UserDTO;
import com.igoal.entity.InfoQueueEntry;
import com.igoal.entity.MemberMail;
import com.igoal.service.MailServiceImpl;
import com.igoal.service.UserManagerExt;
import com.igoal.web.Constants;

public class BroadcastEmailJob {
	private static final Log logger = LogFactory.getLog(BroadcastEmailJob.class);
	
	@Autowired
	MemberMailDAO memberMailDAO;
	@Autowired
	InfoQueueDAO infoQueueDAO;
	@Qualifier("userManagerExt")
	@Autowired
	UserManagerExt userManager;
	@Qualifier("broadcastMailSender")
	@Autowired
	JavaMailSenderImpl broadcastMailSender;
	
	private static boolean block = false;
	
	public BroadcastEmailJob() {
		logger.info("Initialzing [BroadcastEmailJob]...");
	}

	public void execute() throws Exception {
		try {
			logger.info("Starting [BroadcastEmailJob]...");
			if (!block) {
				block = true;
				Long totalEmail = 0l;
				Long sentCount = 0l;
				
				MemberMail memberMail = memberMailDAO.getTopPriorityTask();
				if(memberMail == null){
					block = false;
					logger.info("Stopped [BroadcastEmailJob] without any sending emails");
					return;
				}
				
				memberMail.setSendingStatus(Constants.EMAIL_SENDING);
				memberMail = memberMailDAO.save(memberMail);
				
				String subjectTemplate = memberMail.getSubject();
				String bodyTemplate = memberMail.getBody();
				Map<String, String> param = new HashMap<String, String>();
				param.put("$username", "");
				param.put("$firstName", "");
				param.put("$lastName", "");
				param.put("$date", "");
				
				if(memberMail.isIgoalDB()){					
					String groupNames = memberMail.getReceptionGroups();
					String[] roleNames = groupNames.split(",");
					if(roleNames != null){
						logger.info("Sending broadcast email to igoal's user...");
						for(String roleName : roleNames){
							List<UserDTO> users = userManager.getUserHavingRole(roleName);						
							
							if(users != null){								
								totalEmail = new Long(users.size());
								memberMail.setTotalEmail(totalEmail);
								
								for(UserDTO user : users){								
									param.put("$username", user.getUsername());
									param.put("$firstName", user.getFirstName());
									param.put("$lastName", user.getLastName());
									
									if(sendMail(param, user.getEmail(), subjectTemplate, bodyTemplate)){									
										sentCount ++;
										memberMail.setTotalEmailSent(sentCount);
									}
									
									logger.info("Waiting 2 minutes to send next mail...");
									Thread.sleep(7200l);
								}
							}					
						}
					}
				}
				
				if(memberMail.isMarketingDB()){					
					List<InfoQueueEntry> entries = infoQueueDAO.getAllDisticntRandom();//infoQueueDAO.getAllDistinct();
					if(entries != null){
						logger.info("Sending email to marketing user...");
						totalEmail += new Long(entries.size());
						memberMail.setTotalEmail(totalEmail);
						
						for(InfoQueueEntry entry : entries){
							param.put("$username", entry.getCallName());
							param.put("$firstName", entry.getCallName());
							param.put("$lastName", entry.getCallName());
														
							if(sendMail(param, entry.getEmail(), subjectTemplate, bodyTemplate)){
								sentCount ++;
								memberMail.setTotalEmailSent(sentCount);
							}
							
							logger.info("Waiting 2 minutes to send next mail...");
							Thread.sleep(7200l);
						}
					}
				}
				
				memberMail.setTotalEmail(totalEmail);
				memberMail.setTotalEmailSent(sentCount);
				logger.info("Sending broadcast email finished");
				memberMail.setSendingStatus(Constants.SENT_FINISHED);
				memberMailDAO.save(memberMail);
			}
			logger.info("Stopped [BroadcastEmailJob]");
		} finally {
			block = false;
		}
	}
	
	private boolean sendMail(Map<String, String> param, String email, String subjectTemplate, String bodyTemplate){
		Set<String> paramKey = param.keySet();
		String subject = subjectTemplate;
		String body = bodyTemplate;
		for(String key : paramKey){
			subject = StringUtils.replace(subject, key, param.get(key));
			body = StringUtils.replace(body, key, param.get(key));
		}
		
		return sendMail(email, subject, body);
	}
	
	private boolean sendMail(String to, String subject, String body){
		try {
			logger.info("Sending broadcast email to: " + to);
			MimeMessage message = broadcastMailSender.createMimeMessage();
			MimeMessageHelper helper = new MimeMessageHelper(message, true);
			helper.setFrom(MailServiceImpl.DEFAULT_NOREPLY_FROM);
			helper.setTo(to);
			helper.setSubject(subject);
			helper.setText(body, true);
			broadcastMailSender.send(message);
			logger.info("Email has been sent to " + to + " successfully.");
			return true;
		} catch (Exception e) {
			logger.error(e);
			return false;
		}
	}

}